package com.heima.user.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.common.constants.admin.AdminConstants;
import com.heima.common.exception.CustException;
import com.heima.common.exception.CustomException;
import com.heima.feigns.ArticleFeign;
import com.heima.feigns.WemediaFeign;
import com.heima.model.article.pojos.ApAuthor;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.user.dtos.AuthDTO;
import com.heima.model.user.pojos.ApUser;
import com.heima.model.user.pojos.ApUserRealname;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.user.mapper.ApUserMapper;
import com.heima.user.mapper.ApUserRealnameMapper;
import com.heima.user.service.ApUserRealnameService;
import io.seata.spring.annotation.GlobalTransactional;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
public class ApUserRealnameServiceImpl extends ServiceImpl<ApUserRealnameMapper, ApUserRealname> implements ApUserRealnameService {

    @Autowired
    private ApUserMapper apUserMapper;
    @Autowired
    private WemediaFeign wemediaFeign;
    @Autowired
    private ArticleFeign articleFeign;

    /**
     * 查询列表
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult loadListByStatus(AuthDTO dto) {
        // 1 参数检查
        if (dto == null) {
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID);
        }
        dto.checkParam();

        // 2 条件查询
        Page<ApUserRealname> page = new Page<>(dto.getPage(), dto.getSize());
        LambdaQueryWrapper<ApUserRealname> lambdaQueryWrapper = Wrappers.<ApUserRealname>lambdaQuery();

        if (dto.getStatus() != null) {
            lambdaQueryWrapper.eq(ApUserRealname::getStatus, dto.getStatus());
        }

        IPage<ApUserRealname> resultPage = page(page, lambdaQueryWrapper);

        // 3 返回结果
        return new PageResponseResult(dto.getPage(), dto.getSize(),
                resultPage.getTotal(), resultPage.getRecords());
    }

    //@Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class, timeoutMills = 30000)
    @Override
    public ResponseResult updateStatusById(AuthDTO dto, Short status) {
        if (dto.getId() == null) {
            CustException.cust(AppHttpCodeEnum.PARAM_INVALID, "实名认证id不能为空");
        }
        ApUserRealname apUserRealname = getById(dto.getId());
        if (apUserRealname == null) {
            CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST, "实名认证信息不存在");
        }
        if (!AdminConstants.WAIT_AUTH.equals(apUserRealname.getStatus())) {
            CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST, "实名认证信息非待审核状态");
        }
        ApUser apUser = apUserMapper.selectById(dto.getId());
        if (apUser == null) {
            CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST, "实名认证信息关联app的用户不存在");
        }
        apUserRealname.setUpdatedTime(new Date());
        if (StringUtils.isNotBlank(dto.getMsg())) {
            apUserRealname.setReason(dto.getMsg());
        }
        //审核通过
        if (AdminConstants.PASS_AUTH.equals(status)) {
            RestTemplate restTemplate = new RestTemplate();
            HttpHeaders httpHeaders = new HttpHeaders();
            Map<String, String> map = new HashMap<>();
            httpHeaders.add("apicode", "38b26747fe1d4d2f9d80a66580186b7e");
            httpHeaders.setContentType(MediaType.APPLICATION_JSON);
            //1.根据身份证正面照片 QCR 扫描出 姓名+身份证号
            ResponseEntity idcardOCRresponse = idcardOCR(restTemplate, httpHeaders, map, apUserRealname);
            //2.根据 姓名+身份证号 调用公安部接口 判断真实性 （如果不真实状态修改为 2）
            boolean result = matchIdentity(restTemplate, httpHeaders, map, idcardOCRresponse);
            if (!result){
                apUserRealname.setStatus(AdminConstants.FAIL_AUTH);
                apUserRealname.setReason("经查询，该身份证信息不是真的");
                updateById(apUserRealname);
                return ResponseResult.errorResult(AppHttpCodeEnum.REMOTE_SERVER_ERROR,"经查询，该身份证信息不是真的");
            }
            //使用 活体检测接口 检测liveImage是否为真实自拍 （score < 85 状态修改为 2）
            int score1 = biologicalExamination(restTemplate, httpHeaders, map,apUserRealname);
            if (score1 < 85){
                apUserRealname.setStatus(AdminConstants.FAIL_AUTH);
                apUserRealname.setReason("活体照片检测失败");
                updateById(apUserRealname);
                return ResponseResult.errorResult(AppHttpCodeEnum.REMOTE_SERVER_ERROR,"活体照片检测失败");
            }
            //使用 人证核验接口 判断活体检测照片 和身份证上的照片是否为同一人 (如果不是 score < 85 状态修改为 2）
            int score2 = comparisonsofPersonsandDocuments(restTemplate, httpHeaders, map,apUserRealname);
            if (score1 < 85){
                apUserRealname.setStatus(AdminConstants.FAIL_AUTH);
                apUserRealname.setReason("人证核验失败");
                updateById(apUserRealname);
                return ResponseResult.errorResult(AppHttpCodeEnum.REMOTE_SERVER_ERROR,"人证核验失败");
            }
        }
        apUserRealname.setStatus(status);
        updateById(apUserRealname);
        if (AdminConstants.PASS_AUTH.equals(status)) {
            //4.1 创建自媒体账户
            WmUser wmUser = createWmUser(apUser);
            //4.2 创建作者信息
            createApAuthor(wmUser);
        }
        //分布式事务回滚测试
        /*if(apUser.getId() == 5){
            CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST,"自定义异常");
        }*/
        return ResponseResult.okResult();
    }

    /**
     * 使用 人证核验接口 判断活体检测照片 和身份证上的照片是否为同一人
     * @param restTemplate
     * @param httpHeaders
     * @param map
     * @param apUserRealname
     * @return
     */
    private int comparisonsofPersonsandDocuments(RestTemplate restTemplate, HttpHeaders httpHeaders, Map<String, String> map, ApUserRealname apUserRealname) {
        map.put("idCardImage", apUserRealname.getFontImage());
        map.put("imageType", "URL");
        map.put("liveImage", apUserRealname.getLiveImage());
        HttpEntity<String> formEntry = new HttpEntity<>(JSON.toJSONString(map), httpHeaders); // 封装请求参数
        ResponseEntity<String> comparisonsofPersonsandDocumentsResponse = restTemplate.postForEntity("https://api.yonyoucloud.com/apis/dst/ComparisonsofPersonsandDocuments/ComparisonsofPersonsandDocuments", formEntry, String.class);
        String body = comparisonsofPersonsandDocumentsResponse.getBody();
        JSONObject json = JSONObject.parseObject(body);
        JSONObject data = json.getJSONObject("data");
        return Integer.parseInt(data.getJSONArray("score").toString());
    }

    /**
     * 使用 活体检测接口 检测liveImage是否为真实自拍
     * @param restTemplate
     * @param httpHeaders
     * @param map
     * @param apUserRealname
     * @return
     */
    private int biologicalExamination(RestTemplate restTemplate, HttpHeaders httpHeaders, Map<String, String> map, ApUserRealname apUserRealname) {
        map.put("image", apUserRealname.getLiveImage());
        map.put("imageType", "URL");
        HttpEntity<String> formEntry = new HttpEntity<>(JSON.toJSONString(map), httpHeaders); // 封装请求参数
        ResponseEntity<String> biologicalExaminationResponse = restTemplate.postForEntity("https://api.yonyoucloud.com/apis/dst/Biologicalexamination/Biologicalexamination", formEntry, String.class);
        String body = biologicalExaminationResponse.getBody();
        JSONObject json = JSONObject.parseObject(body);
        JSONObject data = json.getJSONObject("data");
        return Integer.parseInt(data.getJSONArray("score").toString());
    }

    /**
     * 根据身份证正面照片 QCR 扫描出 姓名+身份证号
     *
     * @param restTemplate
     * @param httpHeaders
     * @param map
     * @param apUserRealname
     * @return
     */
    private ResponseEntity idcardOCR(RestTemplate restTemplate, HttpHeaders httpHeaders, Map map, ApUserRealname apUserRealname) {
        map.put("image", apUserRealname.getFontImage());
        map.put("imageType", "URL");
        map.put("ocrType", "0");
        HttpEntity<String> formEntry = new HttpEntity<>(JSON.toJSONString(map), httpHeaders); // 封装请求参数
        ResponseEntity<String> idcardOCRresponse = restTemplate.postForEntity("https://api.yonyoucloud.com/apis/dst/IdcardOCR/IdcardOCR", formEntry, String.class);
        String body = idcardOCRresponse.getBody();
        JSONObject json = JSONObject.parseObject(body);
        String message = json.getJSONArray("message").toString();
        if (!message.equals("成功")){
            CustException.cust(AppHttpCodeEnum.REMOTE_SERVER_ERROR,"身份证正面照片无法识别");
        }
        return idcardOCRresponse;
    }

    /**
     * 根据 姓名+身份证号 调用公安部接口 判断真实性 （如果不真实状态修改为 2）
     *
     * @param restTemplate
     * @param httpHeaders
     * @param map
     * @param response
     * @return
     */
    private boolean matchIdentity(RestTemplate restTemplate, HttpHeaders httpHeaders, Map map, ResponseEntity response) {
        String body = (String) response.getBody();
        JSONObject json = JSONObject.parseObject(body);
        JSONObject data = json.getJSONObject("data");
        String name = data.getJSONArray("name").toString();
        String cardNum = data.getJSONArray("cardNum").toString();
        map.put("idNumber", cardNum);
        map.put("userName", name);
        // 封装请求参数
        HttpEntity<String> formEntry = new HttpEntity<>(JSON.toJSONString(map), httpHeaders);
        // 发送一个post请求
        ResponseEntity<String> matchIdentityresponse = restTemplate.postForEntity("https://api.yonyoucloud.com/apis/dst/matchIdentity/matchIdentity", formEntry, String.class);
        String responseBody = matchIdentityresponse.getBody();
        JSONObject jsonObject = JSONObject.parseObject(responseBody);
        String success = jsonObject.getJSONArray("success").toString();
        return success.equals("true");
    }

    /**
     * 创建自媒体账户
     *
     * @param apUser
     * @return
     */
    private WmUser createWmUser(ApUser apUser) {
        //1 查询自媒体账号是否存在（APP端用户密码和自媒体密码一致）
        ResponseResult<WmUser> wmUserResult = wemediaFeign.findByName(apUser.getName());
        if (!wmUserResult.checkCode()) {
            CustException.cust(AppHttpCodeEnum.REMOTE_SERVER_ERROR, wmUserResult.getErrorMessage());
        }
        WmUser wmUser = wmUserResult.getData();
        if (wmUser != null) {
            CustException.cust(AppHttpCodeEnum.DATA_EXIST, "自媒体用户信息已存在");
        }
        wmUser = WmUser.builder().
                apUserId(apUser.getId()).
                name(apUser.getName()).
                password(apUser.getPassword()).
                salt(apUser.getSalt()).
                phone(apUser.getPhone()).
                image(apUser.getImage()).
                status(AdminConstants.PASS_AUTH.intValue()).
                type(0).
                createdTime(new Date()).build();
        ResponseResult<WmUser> saveResult = wemediaFeign.save(wmUser);
        if (!saveResult.checkCode()) {
            CustException.cust(AppHttpCodeEnum.REMOTE_SERVER_ERROR, saveResult.getErrorMessage());
        }
        return saveResult.getData();
    }

    /**
     * 4.2 创建作者信息
     *
     * @param wmUser
     * @return
     */
    private void createApAuthor(WmUser wmUser) {
        ResponseResult<ApAuthor> apAuthorResult = articleFeign.findByUserId(wmUser.getApUserId());
        if (!apAuthorResult.checkCode()) {
            CustException.cust(AppHttpCodeEnum.REMOTE_SERVER_ERROR, apAuthorResult.getErrorMessage());
        }
        ApAuthor apAuthor = apAuthorResult.getData();
        if (apAuthor != null) {
            CustException.cust(AppHttpCodeEnum.DATA_EXIST, "作者信息已存在");
        }
        apAuthor = ApAuthor.builder().
                name(wmUser.getName()).
                type(AdminConstants.AUTHOR_TYPE).
                userId(wmUser.getApUserId()).
                createdTime(new Date()).
                wmUserId(wmUser.getId()).build();
        ResponseResult responseResult = articleFeign.save(apAuthor);
        if (!responseResult.checkCode()) {
            CustException.cust(AppHttpCodeEnum.REMOTE_SERVER_ERROR, apAuthorResult.getErrorMessage());
        }
    }
}